5.05. Управляющие конструкции и логика
Управляющие конструкции и логика
Все программы управляются с помощью операторов и циклов, которые позволяют:
- принимать решения (условные операторы);
- выполнять повторяющиеся действия (циклы);
- манипулировать данными (арифметические, логические, сравнительные операторы).
Оператор (operator) — это символ или ключевое слово, которое выполняет операцию над одним или несколькими значениями (операндами).
Операторы используются для:
- Манипуляции данными;
- Сравнения значений;
- Управления потоком выполнения программы.
Управляющая конструкция — это элемент языка, который определяет порядок выполнения инструкций в программе.
К ним относятся:
- Условные операторы (if, switch);
- Циклы (for, while, foreach);
- Операторы перехода (break, continue, return, goto).
Они позволяют программе «думать»: принимать решения, повторять действия, выходить из блоков и т.д.
Условная операция — это выражение, которое возвращает разные значения в зависимости от условия.
Самый известный пример — тернарный оператор ? :, который является сокращённой формой if-else.
string result = (age >= 18) ? "Доступ разрешён" : "Доступ запрещён";
Условные операции позволяют писать лаконичный код без развёрнутых блоков if-else.
Операторы делятся на категории по функциональности.
- Арифметические операторы используются для математических вычислений:
| Оператор | Описание | Пример |
|---|---|---|
+ | Сложение | int sum = a + b; |
- | Вычитание | int diff = a - b; |
* | Умножение | int product = a * b; |
/ | Деление | int quotient = a / b; |
% | Остаток от деления | int remainder = a % b; |
При делении целых чисел результат усекается: 5 / 2 = 2, а не 2.5
- Операторы присваивания присваивают значение переменной или изменяют его:
| Оператор | Пример | Аналог |
|---|---|---|
= | x = 5; | нет |
+= | x += 3; | x = x + 3; |
-= | x -= 3; | x = x - 3; |
*= | x *= 3; | x = x * 3; |
/= | x /= 3; | x = x / 3; |
%= | x %= 3; | x = x % 3; |
Такие операторы могут быть составными (комбинируют операцию и присваивание).
- Увеличение и уменьшение значения (
++,--) изменяют на 1. Это соответственно инкремент и декремент:++увеличивает на 1,x++или++x;--уменьшает на 1,x--или--x.
Как обычно, имеется разница между постфиксной и префиксной формами:
int a = 5;
int b = a++; // b = 5, a = 6 (сначала присвоили, потом увеличили)
int c = ++a; // c = 7, a = 7 (сначала увеличили, потом присвоили)
- Операторы сравнения возвращают true или false. Используются в условиях.
| Оператор | Описание | Пример |
|---|---|---|
== | Равно | if (a == b) |
!= | Не равно | if (a != b) |
> | Больше | if (a > b) |
< | Меньше | if (a < b) |
>= | Больше или равно | if (a >= b) |
<= | Меньше или равно | if (a <= b) |
Для сравнения содержимого объектов также можно использовать метод .Equals()
string a = "hello";
string b = "hello";
bool isEqual = a.Equals(b); // true
Как можно понять из перевода с английского, equal это равенство, поэтому это сравнение.
Обратите внимание на важную вещь - больше или равно пишется именно >=, а не =>, ведь => это стрелка.
- Логические операторы используются для объединения или инвертирования условий:
| Оператор | Описание | Пример |
|---|---|---|
&& | Логическое И | if (age > 18 && age < 60) |
! | Логическое НЕ | if (!isAuthorized) |
?? | Оператор объединения со значением по умолчанию (null-coalescing) | string displayName = name ?? "Guest"; |
Самый распространённый пример применения это !имя, означающий НЕимя, буквально.
В C# есть дополнительный оператор ?? (null-coalescing), который возвращает первый операнд, если он не null, иначе второй.
string name = null;
string displayName = name ?? "Гость"; // "Гость"
Это полезно для безопасной работы с nullable-значениями.
- Операторы is (проверка типа объекта) и as (безопасное приведение объекта).
object obj = "Hello";
string str = obj as string;
if (obj is string)
{
Console.WriteLine("Это строка");
}
- Оператор nameof возвращает имя переменной, типа или члена в виде строки:
string paramName = nameof(age); // "age"
Console.WriteLine($"Ошибка в параметре: {paramName}");
Это удобно для сообщений об ошибках, логирования, когда надо вывести имя чего-то.
- Лямбда-оператор
=>используется для определения лямбда-выражений:
Func<int, int> square = x => x * x;
Console.WriteLine(square(5)); // 25
// В LINQ
var even = numbers.Where(x => x % 2 == 0);
Как и в Java, в C# есть методы, которые выполняют функции, аналогичные операторам:
- .Equals() — аналог оператора
==для сравнения содержимого объектов; - .CompareTo() — аналог операторов сравнения (
<,>,<=,>=); - Math класс — аналоги арифметических операций с проверкой на переполнение - Math.Add(), Math.Subtract(), Math.Multiply();
- BitOperations класс — аналоги битовых операций - BitOperations.PopCount() — подсчитывает количество единиц в двоичном представлении числа;
- Convert класс — аналоги операторов приведения типов - Convert.ToInt32(), Convert.ToDouble();
- Object.ReferenceEquals() — проверяет, ссылаются ли два объекта на один и тот же экземпляр (аналог == для ссылок).
Операторы выполняются в определённом порядке. Вот основные уровни (от высшего к низшему):
x++,x--(постфикс);++x, --x(префикс),!,(type);*,/,%;+,-;<,>,<=,>=;==,!=;&&;- `;
?:=,+=,-=и прочие.
Циклы позволяют выполнять блок кода несколько раз, пока выполняется определённое условие.
- for это цикл со счётчиком, который используется, когда известно количество итераций:
for (int i = 0; i < 5; i++) {
Console.WriteLine($"Итерация {i}");
}
Структура:
for (инициализация; условие; шаг) {
// тело цикла
}
- while выполняет код, пока условие истинно:
int count = 0;
while (count < 5) {
Console.WriteLine(count);
count++;
}
Структура:
while (условие) {
//тело цикла
}
- do…while выполняет код хотя бы один раз, затем проверяет условие:
int number;
do {
Console.Write("Введите число больше 0: ");
number = int.Parse(Console.ReadLine());
} while (number <= 0);
Структура:
do {
//тело цикла
} while (условие)
- foreach, перебор коллекций, удобен для массивов, списков, словарей и других перечисляемых типов:
string[] names = { "Alice", "Bob", "Charlie" };
foreach (string name in names) {
Console.WriteLine(name);
}
Структура:
foreach(тип переменная in коллекция) {
//тело цикла
}
Существуют специальные управляющие операторы - break, continue, goto.
Циклы прерываются через ключевое слово break, а продолжаются через continue (переход к следующей итерации). Пример:
for (int i = 0; i < 10; i++) {
if (i == 5) break; // остановится на 5
if (i % 2 == 0) continue; // пропустит чётные числа
Console.WriteLine(i);
}
В чем разница между «Break» и «Continue» в C#?
break: используется в циклах (for и т. д.) и операторах переключения, завершает итерацию/переключение и пропускает весь оставшийся код в цикле или блоке переключения.
continue: используется только в циклах, пропускает весь оставшийся код в цикле и начинает следующую итерацию с начала цикла.
И есть ещё goto - переход к метке. Он редко используется и может усложнить код. Чаще всего его заменяют нормальными управляющими конструкциями.